<?php

namespace App\Repositories\Settings;

use App\Exceptions\SysException;
use App\Facade\AppContext;
use App\Models\BaseModel;
use App\Models\Settings\ApprovalFlow;
use App\Models\Settings\ApprovalFlowNode;
use App\Models\Settings\ApprovalFlowRecord;
use App\Models\System\User;
use App\Repositories\BaseRepository;
use App\Repositories\SaveManyHandler;
use App\Utils\Output;
use App\Utils\Pager;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Throwable;

class ApprovalFlowRepository extends BaseRepository
{
    function adminPager($params = [])
    {
        extract($params);
        $query = ApprovalFlow::query();
        if (!empty($role_id)) {
            $query->where('settings__approval_flows.role_id', '=', $role_id);
        }
        if (!empty($document_type)) {
            $query->where('settings__approval_flows.document_type', '=', $document_type);
        }

        $total = $query->count();
        $query->leftJoin('system__roles', 'system__roles.id', '=', 'settings__approval_flows.role_id');
        $query->select(
            'settings__approval_flows.id',
            'settings__approval_flows.created_at',
            'settings__approval_flows.updated_at',
            'settings__approval_flows.document_type',
            'settings__approval_flows.node_count',
            'settings__approval_flows.document_type as  document_type_text',
            'system__roles.name as role_name',
        );
        $lis = Pager::setPageParams($query, $params, 'id')->get();
        return Output::pager($lis, $total);
    }

    /**
     * 获取对象详情
     * @param int $id
     * @return Output
     */
    function detail(int $id)
    {
        try {
            $entity = ApprovalFlow::find($id);
            if (empty($entity)) {
                return Output::fail(__('common.tips.data_does_not_exist'));
            }
            $nodes = $entity['nodes'];
            foreach ($nodes as $node) {
                $node['role_ids'] = explode(',', $node['role_ids']);
                $node['user_ids'] = explode(',', $node['user_ids']);
                if (empty($node['user_ids'])) {
                    $node['users'] = [];
                } else {
                    $node['users'] = User::query()->whereIn('id', $node['user_ids'])->select('id', 'username', 'name', 'mobile')->get();
                }
            }
            return Output::data($entity);
        } catch (Throwable $exception) {
            return Output::error($exception, __('common.tips.get_data_exception'));
        }
    }

    /**
     * 保存数据
     * @param array $data 数据数组
     * @param int $id 主键 0 新增
     * @return Output
     * @throws Throwable
     */
    function save(array $data, int $id = 0)
    {
        try {
            DB::beginTransaction();
            if ($id) {
                $model = ApprovalFlow::find($id);
                if (empty($model)) {
                    throw new SysException(__('common.tips.data_does_not_exist'));
                }
            } else {
                $model = new ApprovalFlow();
            }
            $nodes = $data['nodes'];
            $data['node_count'] = count($data['nodes']);
            $data['nodes'] = array_values($nodes);
            $model->fill($data)->save();
            $handler = SaveManyHandler::get(ApprovalFlowNode::query(), 'flow_id');
            $handler->setUniqueCall(function ($item) {
                return $item['node_index'];
            });
            $handler->setForeignId($model['id']);
            $handler->setCommonData([
                'flow_id' => $model['id'],
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s')
            ]);
            $handler->setModifyMode(SaveManyHandler::MODIFY_MODE_UPDATE);
            $handler->setAdditionalFields([
                'name',
                'user_ids',
                'role_ids',
                'node_index',
                'pass_next_node_id',
                'refuse_next_node_id'
            ]);
            $handler->save($nodes);
            DB::commit();
            if ($id > 0) {
                return Output::success(__('common.tips.modified_successfully'), $id);
            } else {
                return Output::success(__('common.tips.added_successfully'), $model['id']);
            }
        } catch (\Throwable $exception) {
            DB::rollBack();
            return Output::error($exception, '保存品牌失败');
        }
    }

    /**
     * 审批流程完成回调
     * @param int $id 单价编号
     * @param boolean $status 审批状态
     * @param int $type 单据类型
     * @param int $userId 最后审批人
     * @param string $opinion 最后审批意见
     */
    function complete(int $id, bool $status, int $type, int $userId, string $opinion)
    {
        $handler = resolve('ApprovalFlow/' . $type);
        return $handler->approvalFlowComplete($id, $status, $type, $userId, $opinion);
    }

    /**
     * 检查单据是否还需要审批
     * 需要检查单据被删除等
     * @param int $id 数据对象ID
     * @param int $type 单据类型
     * @return bool 还需要审批返回true 否则返回false
     */
    private function check(int $id, int $type): bool
    {
        $handler = resolve('ApprovalFlow/' . $type);
        return $handler->approvalFlowCheck($id, $type);
    }

    //保存

    /**
     * @throws Throwable
     */
    function approval($data): Output
    {
        $record = ApprovalFlowRecord::find(Arr::get($data, 'node_id', 0));
        if ($record) {
            if ($record['status'] != 3) {
                return Output::fail('该数据可能已被他人审批！');
            }
            if ($this->check($record['document_id'], $record['document_type'])) {
                return Output::fail('单据已被删除或不需要审批');
            }
            try {
                DB::beginTransaction();
                //审批
                $record['opinion'] = Arr::get($data, 'opinion', '');
                $record['status'] = Arr::get($data, 'status', 2);
                $record['user_id'] = AppContext::userId();
                $record->save();
                if ($record['status'] == 1) {
                    //通过
                    $next_node_id = $record->node->pass_next_node_id;
                } else {
                    //未通过
                    $next_node_id = $record->node->refuse_next_node_id;
                }
                if ($next_node_id == -1) {
                    //结束了
                    $this->complete($record['document_id'], $record['status'] == 1, $record['document_type'], $record['user_id'], $record['opinion']);
                    DB::commit();
                    return Output::success('审批成功,审核完成');
                }
                //创建审批节点
                ApprovalFlowRecord::create([
                    'flow_id' => $record['flow_id'],
                    'flow_node_id' => $next_node_id,
                    'status' => 3,
                    'document_id' => $record['document_id'],
                    'document_type' => $record['document_type'],
                ]);
                DB::commit();
                return Output::success('审批成功,审核完成');
            } catch (Throwable $e) {
                DB::rollBack();
                return Output::error($e, '审核失败');
            }
        } else {
            return Output::fail('信息已变更，查看后再试');
        }
    }

    /**
     * @return BaseModel
     */
    function getModel(): BaseModel
    {
        return new ApprovalFlow();
    }
}
